﻿using System.Configuration.Abstractions;
using System.Web.Http;
using SimpleInjector;
using Sustainalytics.AwsS3.Client;
using Sustainalytics.Claims;
using Sustainalytics.ClientDW.Entities;
using Sustainalytics.DataLayer.Shared;
using Sustainalytics.ESG.Entities;
using Sustainalytics.ESGRatings.BusinessLogic;
using Sustainalytics.ESGRatings.BusinessLogic.ESGOnlineReport;
using Sustainalytics.MongoDB.Extensions;
using Xunit.Abstractions;
using Xunit.Sdk;
using Sustainalytics.Entities.ESGRatings;
using Sustainalytics.ESGRatings.BusinessLogic.ESGProfile;
using Sustainalytics.ReportGenerator.BL;
using System.Collections.Generic;

namespace Sustainalytics.PdfGeneration.Service
{
    public static class CompositionRoot
    {
        private static Dictionary<string, string> _connectionStrings = null;
        public static Container RegisterDependencies(HttpConfiguration config, Dictionary<string, string> connectionStrings = null)
        {
            _connectionStrings = connectionStrings;
            var container = new Container();

            container.Options.DefaultScopedLifestyle = new SimpleInjector.Lifestyles.AsyncScopedLifestyle();
            container.RegisterWebApiControllers(config);

            var clientPlatformConnectionString = ConfigurationManager.Instance.ConnectionStrings["ClientPlatform"].ConnectionString;

            var accessKey = ConfigurationManager.Instance.AppSettings["accesKeyId"].ToString();
            var secretAccessKey = ConfigurationManager.Instance.AppSettings["awsSecretKey"].ToString(); 
            var serviceEndPoint = ConfigurationManager.Instance.AppSettings["s3ServiceEndPoint"].ToString(); 

            container.RegisterMisc(accessKey, secretAccessKey, serviceEndPoint);

            container.RegisterLoggers();

            container.RegisterCollections(clientPlatformConnectionString);

            container.RegisterRepositories(clientPlatformConnectionString);

            container.RegisterBussinesLogic();

            container.Verify();
            return container;
        }


        private static void RegisterCollections(this Container container,
           string clientPlatformConnectionString)
        {
            var clientDWConnectionString = string.Empty;
            var archiveDWConnectionString = string.Empty;
            if (_connectionStrings != null)
            {
                clientDWConnectionString = _connectionStrings["ClientDW"];
                archiveDWConnectionString = _connectionStrings["DWArchive"];
            }
            else
            {
                clientDWConnectionString = MongoFactory.GetConnectionStrings().ClientDW;
                archiveDWConnectionString = MongoFactory.GetConnectionStrings().DWArchive;
            }
               
            container.Register(typeof(IRepositoryCollection<SubPeerGroupKeyEsgIssue>), () => new RepositoryCollection<SubPeerGroupKeyEsgIssue>(clientDWConnectionString));
            container.Register(typeof(IRepositoryCollection<Analyst>), () => new RepositoryCollection<Analyst>(clientDWConnectionString));
            container.Register(typeof(IRepositoryCollection<IndicatorTemplate>), () => new RepositoryCollection<IndicatorTemplate>(clientDWConnectionString));
            container.Register(typeof(IRepositoryCollection<CorporateData>), () => new RepositoryCollection<CorporateData>(clientDWConnectionString));
            container.Register(typeof(IRepositoryCollection<FinancialData>), () => new RepositoryCollection<FinancialData>(clientDWConnectionString));
            container.Register(typeof(IRepositoryCollection<RPCompanyProfile>), () => 
                new RepositoryCollection<RPCompanyProfile>(clientDWConnectionString));
            container.Register(typeof(IRepositoryCollection<RPCompanyESGComputationResult>), () =>
                new RepositoryCollection<RPCompanyESGComputationResult>(clientDWConnectionString));
            container.Register(typeof(IRepositoryCollection<CompanyHistoricalPerformance>), () => new RepositoryCollection<CompanyHistoricalPerformance>(archiveDWConnectionString));
            container.Register(typeof(IRepositoryCollection<RPIndicatorExtended>), () => new RepositoryCollection<RPIndicatorExtended> (clientDWConnectionString));
            container.Register(typeof(IRepositoryCollection<RPControversyIndicator>), () => new RepositoryCollection<RPControversyIndicator> (clientDWConnectionString));
            container.Register(typeof(IRepositoryCollection<ComparisonGroupControversy>), () => new RepositoryCollection<ComparisonGroupControversy>(clientDWConnectionString));
            container.Register(typeof(IRepositoryCollection<EventIndicator>), () => new RepositoryCollection<EventIndicator>(clientDWConnectionString));
            container.Register(typeof(IRepositoryCollection<Incident>), ()=> new RepositoryCollection<Incident>(clientDWConnectionString));
            container.Register(typeof(IRepositoryCollection<CompanyKeyESGIssue>), () => new RepositoryCollection<CompanyKeyESGIssue>(clientDWConnectionString));
            container.Register(typeof(IRepositoryCollection<Source>), () => new RepositoryCollection<Source>(clientDWConnectionString));
            container.Register(typeof(IRepositoryCollection<ESGProfile>), ()=> new RepositoryCollection<ESGProfile>(clientPlatformConnectionString));
            container.Register(typeof(IRepositoryCollection<ReferenceUniverse>), () => new RepositoryCollection<ReferenceUniverse>(clientDWConnectionString));
            container.Register(typeof(IRepositoryCollection<SustainalyticsSubIndustry>), ()=>new RepositoryCollection<SustainalyticsSubIndustry>(clientDWConnectionString));
            container.Register( ()=> MongoFactory.GetCollectionFromDatabase<CorporateData>(clientDWConnectionString));
            container.Register(() => MongoFactory.GetCollectionFromDatabase<RPESGResearchState>(clientDWConnectionString));
            container.Register(() => MongoFactory.GetCollectionFromDatabase<CompanyKeyESGIssue>(clientDWConnectionString));
        }

        private static void RegisterLoggers(this Container container)
        {
            container.RegisterCollection<ILogPdf>(new[] { typeof(PdfEmailLogger) });
        }

        private static void RegisterRepositories(this Container container,
           string clientPlatformConnectionString)
        {
            var clientDWConnectionString = string.Empty;
            if (_connectionStrings != null)
            {
                clientDWConnectionString = _connectionStrings["ClientDW"];
            }
            else
            {
                clientDWConnectionString = MongoFactory.GetConnectionStrings().ClientDW;
            }
            container.Register(typeof(IRepositoryCollection<WeightMatrix>), () => new RepositoryCollection<WeightMatrix>(clientDWConnectionString));
            container.Register(typeof(IKeyEsgIssuesRepository), () => new KeyEsgIssuesRepository(clientPlatformConnectionString));

        }

        private static void RegisterBussinesLogic(this Container container)
        {
            container.Register(typeof(IESGProfileManagement), ()=> new ESGProfileManagement(
                container.GetInstance<IRepositoryCollection<ESGProfile>>(),
                container.GetInstance<IRepositoryCollection<ReferenceUniverse>>(),
                container.GetInstance<IRepositoryCollection<WeightMatrix>>()
                ));
            container.Register(typeof(IHistoricalDataBusinessLogicUnit), ()=>new HistoricalDataBusinessLogicUnit(container.GetInstance<IRepositoryCollection<CompanyHistoricalPerformance>>()));
        }

        private static void RegisterMisc(this Container container, string accessKey, string secretAccessKey, string serviceEndPoint)
        {
           
           container.Register(typeof(IClaimsChecker), ()=> new ClaimsChecker());
           container.Register(typeof(ITestOutputHelper), ()=>new TestOutputHelper());
           container.RegisterSingleton(typeof(IS3Client), ()=>new S3Client(new S3ClientSettings()
                {
                    AccessKey = accessKey,
                    SecretAccessKey = secretAccessKey,
                    ServiceEndPoint = serviceEndPoint,
                }

                ));

        }
    }
}
